#include "Entrada.h"

Entrada::Entrada(int id, long numeroEstacionamiento) {
	this->id = id;
	this->procesoPrincipal = new Cola<mensaje>(
			Utils::NOMBRE_ARCHIVO_COLA_PROCESO_PRINCIPAL, 'A');
	this->entradaDeAutos = new Cola<autoSerializable>(
			Utils::NOMBRE_ARCHIVO_ENTRADA, 'A');
	this->simulacionHandler = new SimulacionHandler();
	SignalHandler::getInstance()->registrarHandler(SIGINT,
			this->simulacionHandler);
	this->numeroEstacionamiento = numeroEstacionamiento;
	lock = new LockFile((char *) Utils::NOMBRE_ARCHIVO_PARA_LOG);
	string mensaje = "Se crea entrada : " + to_string(id)
			+ " para estacionamiento : " + to_string(numeroEstacionamiento)
			+ "\n";
	char* log = (char*) mensaje.c_str();
	lock->escribirConLock(log, strlen(log));
}

void Entrada::iniciar() {
	int procId = getpid();
	bool terminar = false;
	while (!terminar) {
		procId = getpid();
		autoSerializable autoSerializable;
		int resultado = this->entradaDeAutos->leer(
				this->numeroEstacionamiento + 1, &autoSerializable);
		if (resultado != -1) {
			if (autoSerializable.tipoMensaje == TIPO_MENSAJE_FIN) {
				terminar = true;
			} else {
				Auto autoEntrando(autoSerializable.idAuto,
						this->numeroEstacionamiento);
				mensaje mensaje;
				mensaje.mtype = MTYPE_PROCESO_GENERAL;
				mensaje.tipoMensaje = 1;
				mensaje.mtypeProximo = (long) getpid();
				mensaje.numeroEstacionamiento = this->numeroEstacionamiento;
				this->procesoPrincipal->escribir(mensaje);
				resultado = this->procesoPrincipal->leer(getpid(), &mensaje);
				if (resultado != -1) {
					int pos = mensaje.lugarDisponible;
					if (pos != -1) {
						procId = fork();
						if (procId == 0) {
							autoEntrando.setPos(pos);
							autoEntrando.estacionar();
							autoEntrando.salir();
							terminar = true;
						}
					} else {
						string mensaje = "Vino el auto : "
								+ to_string(autoEntrando.getId())
								+ " pero no hay lugar en el estacionamiento : "
								+ to_string(numeroEstacionamiento);
						char* log = (char*) mensaje.c_str();
						lock->escribirConLock(log, strlen(log));
					}
				} else {
					cout << "Error al leer del proceso general desde entrada: "
							<< this->getId() << endl;
				}
			}
		} else {
			cout << "Error al leer en Entrada: " << this->getId() << endl;
		}
	}
	if (procId != 0) {
		string mensaje = "La entrada : " + to_string(id)
				+ " para estacionamiento : " + to_string(numeroEstacionamiento)
				+ " finaliza\n";
		char* log = (char*) mensaje.c_str();
		lock->escribirConLock(log, strlen(log));
	}
}

int Entrada::getId() {
	return this->id;
}

Entrada::~Entrada() {
	SignalHandler::getInstance()->removerHandler(SIGINT);
	SignalHandler::destruir();
	delete this->simulacionHandler;
	delete this->entradaDeAutos;
}

